<template>
  <div class="mindmap-controls">
    <!-- 缩放控制 -->
    <div class="zoom-controls">
      <button class="control-btn zoom-btn" @click="zoomOut" title="缩小">
        <img :src="jianImage" alt="缩小" class="zoom-icon" />
      </button>
      <span class="zoom-level">{{ zoomLevel }}%</span>
      <button class="control-btn zoom-btn" @click="zoomIn" title="放大">
        <img :src="addImage" alt="放大" class="zoom-icon" />
      </button>
    </div>

    <!-- 重置视图按钮 -->
    <button class="control-btn reset-btn" @click="resetView" title="重置视图">
      <img :src="reastImage" alt="重置视图" class="reset-icon" />
    </button>

    <!-- 收缩/展开按钮 -->
    <button 
      class="control-btn collapse-btn" 
      @click="toggleCollapse"
      :title="isCollapsed ? '展开所有节点' : '收缩所有节点'"
    >
      <img :src="shouzhanImage" alt="收缩/展开" class="collapse-icon" />
    </button>
  </div>
</template>

<script setup lang="ts">
/**
 * 思维导图控制按钮组件
 * 
 * 功能描述：
 * 1. 提供思维导图的缩放控制（放大、缩小）
 * 2. 提供视图重置功能（自适应画布并居中）
 * 3. 提供全图展开/收缩功能
 * 
 * 交互方式：
 * - 点击按钮触发相应事件，通过 emit 通知父组件或直接操作 Markmap 实例
 */

import { ref, nextTick } from 'vue'

// 导入图片资源
import jianImage from '../../assets/MindMapControls/icon-zoom-out.png'
import addImage from '../../assets/MindMapControls/icon-zoom-in.png'
import reastImage from '../../assets/MindMapControls/icon-reset.png'
import shouzhanImage from '../../assets/MindMapControls/icon-toggle-expand.png'

// ==================== 组件接口 ====================

/** 组件 Props 定义 */
const props = defineProps<{
  /** Markmap 实例对象，用于直接操作导图 */
  markmapInstance: any
  /** 原始数据树，用于展开/收缩时的状态管理 */
  rawTree: any
}>()

/** 组件 Events 定义 */
const emit = defineEmits<{
  /** 更新缩放级别事件 */
  updateZoomLevel: [level: number]
  /** 更新折叠状态事件 */
  updateCollapsed: [collapsed: boolean]
  /** 重新应用样式事件 */
  reapplyStyles: []
}>()

// ==================== 响应式状态 ====================

/** 当前缩放级别 (百分比，如 100 表示 100%) */
const zoomLevel = ref<number>(50)
/** 当前是否处于收缩状态 */
const isCollapsed = ref<boolean>(false)

// ==================== 辅助函数 ====================

/**
 * 获取当前实际缩放比例 (scale)
 * 
 * 优先从 Markmap 实例状态中获取，如果不存在则尝试解析 SVG 的 transform 属性
 * @returns 当前缩放比例 (1.0 = 100%)
 */
const getCurrentScale = (): number => {
  if (props.markmapInstance?.state?.zoom) return props.markmapInstance.state.zoom
  
  // 降级方案：从 DOM 解析
  const svgEl = document.querySelector('#mindMapContainer svg') as SVGSVGElement | null
  if (svgEl) {
    const transform = svgEl.style.transform || ''
    const match = transform.match(/scale\(([^)]+)\)/)
    if (match) {
      const parsed = parseFloat(match[1])
      if (!isNaN(parsed)) return parsed
    }
  }
  return 1
}

/**
 * 应用新的绝对缩放比例
 * 
 * @param newScale - 新的缩放比例
 */
const applyScale = (newScale: number) => {
  const svgEl = document.querySelector('#mindMapContainer svg') as SVGSVGElement | null
  if (!svgEl) return
  
  // 保留现有的平移 (translate)，仅替换缩放 (scale)
  const transform = svgEl.style.transform || ''
  let translateX = 0, translateY = 0
  const translateMatch = transform.match(/translate\(([^,]+),\s*([^)]+)\)/)
  if (translateMatch) {
    translateX = parseFloat(translateMatch[1]) || 0
    translateY = parseFloat(translateMatch[2]) || 0
  }
  
  // 应用新的 transform
  svgEl.style.transform = `translate(${translateX}px, ${translateY}px) scale(${newScale})`
  
  // 同步更新 Markmap 实例状态
  if (props.markmapInstance?.state) {
    props.markmapInstance.state.zoom = newScale
  }
  
  // 触发更新事件
  updateZoomLevel()
}

/**
 * 更新并广播当前的缩放级别
 * 
 * 计算当前的缩放百分比，限制在 10% - 300% 之间，并通知父组件
 */
const updateZoomLevel = () => {
  let scale = 1
  if (props.markmapInstance && props.markmapInstance.state?.zoom) {
    scale = props.markmapInstance.state.zoom
  } else {
    // 降级方案
    const svgEl = document.querySelector('#mindMapContainer svg') as SVGSVGElement | null
    if (svgEl) {
      const transform = svgEl.style.transform || ''
      const match = transform.match(/scale\(([^)]+)\)/)
      if (match) {
        const parsed = parseFloat(match[1])
        if (!isNaN(parsed)) scale = parsed
      }
    }
  }
  
  const percent = Math.round(scale * 100)
  const newLevel = Math.min(300, Math.max(10, percent))
  zoomLevel.value = newLevel
  emit('updateZoomLevel', newLevel)
}

/**
 * 居中 SVG 元素
 * 
 * 计算 SVG 内容与容器中心的偏移量，并调整 translate 值以实现居中
 */
const centerSvg = () => {
  const svg = document.querySelector('#mindMapContainer svg') as SVGSVGElement | null
  if (svg) {
    const container = document.getElementById('mindMapContainer')
    if (container) {
      const containerRect = container.getBoundingClientRect()
      const svgRect = svg.getBoundingClientRect()

      const containerCenterX = containerRect.width / 2
      const containerCenterY = containerRect.height / 2

      // SVG 当前的视觉中心
      const svgCenterX = svgRect.left - containerRect.left + svgRect.width / 2
      const svgCenterY = svgRect.top - containerRect.top + svgRect.height / 2

      const offsetX = containerCenterX - svgCenterX
      const offsetY = containerCenterY - svgCenterY

      const currentTransform = svg.style.transform || ''
      const translateMatch = currentTransform.match(/translate\(([^,]+),\s*([^)]+)\)/)
      let currentX = 0, currentY = 0
      if (translateMatch) {
        currentX = parseFloat(translateMatch[1])
        currentY = parseFloat(translateMatch[2])
      }

      const scaleMatch = currentTransform.match(/scale\(([^)]+)\)/)
      const scale = scaleMatch ? scaleMatch[1] : '1'
      
      svg.style.transform = `translate(${currentX + offsetX}px, ${currentY + offsetY}px) scale(${scale})`
    }
  }
}

/**
 * 自适应内容并居中 (Promise 包装)
 */
const fitToContent = () => {
  if (!props.markmapInstance) return Promise.resolve()

  return Promise.resolve()
    .then(() => props.markmapInstance.fit())
    .then(() => {
      centerSvg()
      updateZoomLevel()
    })
    .catch((error) => {
      console.error('自适应内容失败:', error)
    })
}

/**
 * 递归收缩所有节点
 * @param node - 当前节点
 */
const collapseAll = (node: any) => {
  if (node.payload) {
    node.payload.fold = 1 // 1 表示折叠
  }
  if (node.children) {
    node.children.forEach((child: any) => collapseAll(child))
  }
}

/**
 * 递归展开所有节点
 * @param node - 当前节点
 */
const expandAll = (node: any) => {
  if (node.payload) {
    node.payload.fold = 0 // 0 表示展开
  }
  if (node.children) {
    node.children.forEach((child: any) => expandAll(child))
  }
}

// ==================== 控制按钮功能 ====================

/**
 * 放大视图 (+10%)
 */
const zoomIn = () => {
  if (!props.markmapInstance) return Promise.resolve()

  return Promise.resolve()
    .then(() => {
      const currentScale = getCurrentScale()
      const targetPercent = Math.min(300, Math.round(currentScale * 100 + 10))
      const newScale = targetPercent / 100
      applyScale(newScale)
    })
    .catch((error) => {
      console.warn('放大失败:', error)
    })
}

/**
 * 缩小视图 (-10%)
 */
const zoomOut = () => {
  if (!props.markmapInstance) return Promise.resolve()

  return Promise.resolve()
    .then(() => {
      const currentScale = getCurrentScale()
      const targetPercent = Math.max(10, Math.round(currentScale * 100 - 10))
      const newScale = targetPercent / 100
      applyScale(newScale)
    })
    .catch((error) => {
      console.warn('缩小失败:', error)
    })
}

/**
 * 重置视图
 * 1. 自适应内容
 * 2. 强制缩放到 100%
 * 3. 重新居中
 */
const resetView = () => {
  if (!props.markmapInstance) return
  fitToContent()
  // 强制缩放到 100%
  applyScale(1)
  // 在 scale=1 的情况下重新计算居中位置
  nextTick(() => {
    centerSvg()
  })
}

/**
 * 切换 全展开 / 全收缩 状态
 */
const toggleCollapse = () => {
  if (!props.markmapInstance || !props.rawTree) return

  // 创建数据副本以避免修改原始数据
  const newRoot = JSON.parse(JSON.stringify(props.rawTree))

  if (isCollapsed.value) {
    // 当前为收起状态 → 展开所有节点
    expandAll(newRoot)
    isCollapsed.value = false
  } else {
    // 当前为展开状态 → 收缩所有节点，只保留第0级（根节点）
    collapseAll(newRoot)
    // 确保根节点保持展开状态
    if (newRoot.payload) {
      newRoot.payload.fold = 0
    }
    isCollapsed.value = true
  }

  emit('updateCollapsed', isCollapsed.value)
  props.markmapInstance.setData(newRoot)

  // 更新视图布局
  setTimeout(() => {
    props.markmapInstance.fit().then(() => {
      centerSvg()
      updateZoomLevel()
      // 数据更新后重新应用样式
      emit('reapplyStyles')
    })
  }, 100)
}

// ==================== 对外暴露 ====================
defineExpose({
  updateZoomLevel,
  zoomLevel,
  isCollapsed
})
</script>

<style scoped>
/* 思维导图控制按钮样式 */
.mindmap-controls {
  position: absolute;
  bottom: 8px;
  right: 8px;
  display: flex;
  gap: 6px;
  align-items: center;
  z-index: 1000;
}

/* 控制按钮基础样式 */
.control-btn {
  width: 36px;
  height: 36px;
  background: rgba(255, 255, 255, 0.2);
  border: 1px solid rgba(255, 255, 255, 0.3);
  border-radius: 6px;
  color: white;
  font-size: 18px;
  cursor: pointer;
  transition: all 0.3s ease;
  backdrop-filter: blur(10px);
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 0;
}

.control-btn:hover {
  background: rgba(255, 255, 255, 0.3);
  border-color: rgba(255, 255, 255, 0.5);
  transform: translateY(-2px);
  box-shadow: 0 4px 12px rgba(0, 0, 0, 0.2);
}

.control-btn:active {
  transform: translateY(0);
}

/* 缩放控制组 */
.zoom-controls {
  display: flex;
  align-items: center;
  gap: 6px;
  background: transparent;
  padding: 4px 8px;
  border: none;
}

.zoom-btn {
  width: 32px;
  height: 32px;
  background: transparent !important;
  border: none !important;
  padding: 0;
  display: flex;
  align-items: center;
  justify-content: center;
}

.zoom-btn:hover {
  background: transparent !important;
  transform: scale(1.1);
}

/* 缩放百分比显示 */
.zoom-level {
  font-family: Roboto, sans-serif;
  font-size: 14px;
  font-weight: normal;
  line-height: normal;
  text-align: center;
  letter-spacing: 0em;
  font-variation-settings: "opsz" auto;
  font-feature-settings: "kern" on;
  color: #D4FFEF;
  min-width: 50px;
  user-select: none;
}

/* 缩放图标 */
.zoom-icon,
.collapse-icon,
.reset-icon {
  width: 24px;
  height: 24px;
  object-fit: contain;
}

/* 收缩按钮和重置按钮 */
.collapse-btn,
.reset-btn {
  background: transparent !important;
  border: none !important;
  padding: 0;
}

.collapse-btn:hover,
.reset-btn:hover {
  background: transparent !important;
  transform: scale(1.1);
}
</style>
